﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using Snowdreamist;
using Snowdreamist.Collection;

namespace CompositionPlugin.Service
{
    public class ModuleRepository : IModuleRepository
    {
        public ModuleRepository()
        {
            // import modules
            this._importedPlugins = SystemRuntime.Current.Composition.Container.GetExports<IModule, IModuleMetadata>();
            this._moduleDefinitions = new ConcurrentObservableCollection<ModuleDefinition>(this._importedPlugins.Select(p => new ModuleDefinition(p)));
            this.Modules = new ReadonlyConcurrentObservableCollection<ModuleDefinition>(this._moduleDefinitions);
        }

        public virtual void Initialize() { }

        public virtual void OnRuntimeDisposing()
        {
            this._moduleDefinitions.Dispose();
        }

        public ReadonlyConcurrentObservableCollection<ModuleDefinition> Modules { get; private set; }

        public ModuleDefinition GetModuleDefinition<T>()
        {
            var modules = this._moduleDefinitions.Where(p => p.Metadata.ModuleType == typeof(T)).ToArray();
            if (modules.Length == 0)
            {
                return null;
            }
            else if (modules.Length > 1)
            {
                throw new MultipleValuesFoundException();
            }
            else
            {
                return modules[0];
            }
        }

        public ModuleDefinition GetModuleDefinition(string name)
        {
            var modules = this._moduleDefinitions.Where(p => string.Compare(p.Metadata.Name, name, true) == 0).ToArray();
            if (modules.Length == 0)
            {
                return null;
            }
            else if (modules.Length > 1)
            {
                throw new MultipleValuesFoundException();
            }
            else
            {
                return modules[0];
            }
        }

        public event EventHandler ModuleChanged;

        protected void OnModuleChanged()
        {
            if (this.ModuleChanged != null)
                this.ModuleChanged(this, new EventArgs());
        }

        private IEnumerable<Lazy<IModule, IModuleMetadata>> _importedPlugins;

        private ConcurrentObservableCollection<ModuleDefinition> _moduleDefinitions;
    }
}